package com.heima.comment.service.impl;

import java.math.BigDecimal;
import java.util.*;

import com.heima.aliyun.GreenTextScan;
import com.heima.comment.service.CommentHotService;
import com.heima.comment.service.CommentService;
import com.heima.common.exception.CustomException;
import com.heima.feigns.user.UserFeign;
import com.heima.model.comment.dto.CommentDto;
import com.heima.model.comment.dto.CommentLikeDto;
import com.heima.model.comment.dto.CommentSaveDto;
import com.heima.model.comment.pojo.ApComment;
import com.heima.model.comment.pojo.ApCommentLike;
import com.heima.model.comment.vo.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.threadlocal.AppThreadLocalUtils;
import com.heima.model.user.pojo.ApUser;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Slf4j
public class CommentServiceImpl implements CommentService {
    @Autowired
    UserFeign userFeign;

    @Autowired
    MongoTemplate mongoTemplate;

    @Autowired
    CommentHotService commentHotService;

    @Override
    public ResponseResult saveComment(CommentSaveDto dto) {
        //检查参数   前面注解已经判断过
        //通过app网关
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null) {
            throw new CustomException(AppHttpCodeEnum.NEED_LOGIN);
        }
        //调用远程接口查询user信息
        user = userFeign.findUserById(Long.valueOf(user.getId()));
        if (user == null) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST, "未获取到用户信息");
        }
        //调用阿里云进行评论内容文本检测
        //引入阿里云依赖
        //注入GreenTextScan
        //扫描文本  根据结果进行处理
        Boolean isTextScan = handleTextScan(dto.getContent());
        if (!isTextScan) return null;
        log.info("当前处理的评论,通过了阿里云的文本审核");

        //保存评论信息
        ApComment apComment = new ApComment();
        apComment.setAuthorId(user.getId());
        apComment.setAuthorName(user.getName());
        apComment.setEntryId(dto.getArticleId());
        apComment.setType((short) 0);//0表示文章
        apComment.setContent(dto.getContent());
        apComment.setImage(user.getImage());
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setFlag((short) 0);//0表示普通文章
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());

        mongoTemplate.insert(apComment);

        return ResponseResult.okResult();
    }

    @Resource(name = "likesLock")//按照bean的名称获取    锁可以有多个   对应一个key值      获取锁  就是获取key
     RLock likesLock;


    //@Autowired//按照类型获取



    //@Transactional
    @Override//点赞评论
    public ResponseResult like(CommentLikeDto dto) {
        //检测参数(compantid   方式)

        //是否登录
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null) {
            throw new CustomException(AppHttpCodeEnum.NEED_LOGIN);//多表查询时用到事务,throw
        }

        likesLock.lock();//set  key   分布式锁   指允许一个线程执行
        try {
            //先查询出评论的信息
            ApComment apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
            if (apComment == null) {
                throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
            }

            //检验出是否重复点赞

            //根据作者id和评论id  查询出一个评论点赞的实体
            Query query = Query.query(Criteria.where("authorId").is(user.getId()).and("commentId").is(dto.getCommentId()));
            ApCommentLike apCommentLike = mongoTemplate.findOne(query, ApCommentLike.class);

            if (apCommentLike != null && dto.getOperation().intValue() != 1) {
                throw new CustomException(AppHttpCodeEnum.DATA_EXIST, "请勿重复点赞");
            }
            //根据operation进行判断   0点赞  1取消点赞
            if (dto.getOperation().intValue() == 0) {
                //如果为0  将评论点赞数量加1    保存点赞信息

                apComment.setLikes(apComment.getLikes() + 1);
                mongoTemplate.save(apComment);//类型自动判断  修改评论信息

                ApCommentLike like = new ApCommentLike();
                like.setAuthorId(user.getId());
                like.setCommentId(dto.getCommentId());
                like.setOperation((short) 0);

                mongoTemplate.save(like);
                //如果点赞大于等于5  就有资格竞争热点评论,普通评论
                if (apComment.getLikes() >= 5 && apComment.getFlag().intValue() == 0) {
                    //计算热点评论的方法  文章id  把文章下所有的热评查询出来    参数2  当前的评论信息
                    commentHotService.hotCommentExecutor(apComment.getEntryId(), apComment);

                }


            } else {
                //如果为1  将评论点赞数量  -1    删除之前的点赞信息
                //要考虑点赞数为负的情况
                apComment.setLikes(apComment.getLikes() < 1 ? 0 : apComment.getLikes() - 1);
                mongoTemplate.save(apComment);//修改评论信息

                mongoTemplate.remove(query, ApCommentLike.class);//删除之前的点赞信息


            }


            Integer likes = apComment.getLikes();
            Map map = new HashMap<>();
            map.put("likes", likes);
            return ResponseResult.okResult(map);
        }finally {
            likesLock.unlock();//删除锁,在final中
        }
    }

    @Override//根据文章id查询评论列表
    public ResponseResult findByArticleId(CommentDto dto) {
        //检查参数
        dto.checkParam();

        List<ApComment> apComments=null;

        if (dto.getIndex().intValue()==1){

            //查询首页
            //先查询热点评论
            //热点文章按照点赞数排序,只能为5条,小于10条
            Query hotQuery = Query.query(Criteria.where("entryId").is(dto.getArticleId()).and("createdTime").lt(dto.getMinDate()).and("flag").is(1)).with(Sort.by(Sort.Direction.DESC,"likes")).limit(dto.getSize());

             apComments = mongoTemplate.find(hotQuery, ApComment.class);
            if (apComments!=null&&apComments.size()>0){
                List<ApComment> normalComments = getNormalComments(dto, dto.getSize() - apComments.size());
                apComments.addAll(normalComments);//热点+普通评论
            }else {
                //是首页,但没有热点文章数据
                 apComments = getNormalComments(dto, dto.getSize());
            }

        }else {
            //不是首页,热点文章为空
            //查询更多   普通查询
            //查询评论数据

            apComments = getNormalComments(dto, dto.getSize());

        }

        //判断当前用户是否登录
        ApUser user = AppThreadLocalUtils.getUser();
        if (user==null|| apComments ==null||apComments.size()==0){
            //如果没有登录,查询封装结果返回
            return ResponseResult.okResult(apComments);
        }
        //如果登录了,查看当前分页中的评论信息,哪些评论点过赞
        //用户id  评论id
        List<String> commentIds = apComments.stream().map(ApComment::getId).collect(Collectors.toList());


        Query query1 = Query.query(Criteria.where("authorId").is(user.getId()).and("commentId").in(commentIds));
        //在当前分页数据下,登录用户所点过赞的所有数据
        List<ApCommentLike> apCommentLikes = mongoTemplate.find(query1, ApCommentLike.class);
        //点过赞的评论id
        List<String> commentLikesIds = apCommentLikes.stream().map(ApCommentLike::getCommentId).collect(Collectors.toList());

        List<ApCommentVo> apCommentVoList = new ArrayList<>();
        apComments.forEach(apComment -> {
            ApCommentVo apCommentVo = new ApCommentVo();
            BeanUtils.copyProperties(apComment,apCommentVo);
            if (commentLikesIds.contains(apComment.getId())){
                apCommentVo.setOperation((short)0);
            }
            apCommentVoList.add(apCommentVo);
        });

        return ResponseResult.okResult(apCommentVoList);
    }


    @Autowired
    GreenTextScan greenTextScan;

    //处理阿里云文本审核
    private Boolean handleTextScan(String content) {
        boolean flag = true;
        try {
            Map map = greenTextScan.greenTextScan(content);
            String suggestion = (String) map.get("suggestion");
            if ("review".equals(suggestion)) {
                flag = false;
                log.info("内容中包含不确定因素,请人工审核");
            }
            if ("block".equals(suggestion)) {
                flag = false;
                log.info("文本中包含敏感词汇");
            }
        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
            log.info("阿里云审核失败,转为人工");
        }
        return flag;
    }


    //抽取的方法
    private List<ApComment> getNormalComments(CommentDto dto, Integer size) {//size是变量,可变
        Query query = Query.query(Criteria.where("entryId").is(dto.getArticleId())
                .and("createdTime").lt(dto.getMinDate()).and("flag").is(0))
                .with(Sort.by(Sort.Direction.DESC, "createdTime"))
                .limit(size);
        return mongoTemplate.find(query, ApComment.class);
    }
}
